<template>
  <div class="table-container"  @click="handleClickEvent" :style="{ '--local-mount-height': cssVar ? `var(${cssVar})` : '100%' }">
    <!-- 虚拟滚动容器 -->
    <div class="image-grid-container" ref="gridContainer" @scroll.passive="handleScroll">
      <div class="image-grid-phantom"  :style="{ height: totalHeight + 'px' }"></div>

      <div class="image-grid-content"
           :style="{
             transform: `translateY(${startRow * rowHeight}px)`,
             gridTemplateColumns: `repeat(${columnCount}, 1fr)`
           }"
           v-loading="state.loading">
        <!-- 只渲染可见区域的图片卡片 -->
        <div v-for="(image, index) in visibleImages" :key="image.id" class="grid-item">
          <el-card shadow="hover" class="image-card"
                   :style="{ height: cardHeight + 'px', width: '100%' }"
                   @contextmenu.prevent="onContextmenu(image, $event)">
            <template #header>
              <div class="card-header">
                <div class="icon-buttons">
                  <!-- 图片按钮 -->
                  <el-tooltip :content="$t('message.common.image')" placement="top">
                    <el-button :type="state.activeTabs[image.id] === 'image' ? 'primary' : 'text'"
                      @click.stop="changeTab(image.id, 'image')">
                      <el-icon>
                        <Picture />
                      </el-icon>
                    </el-button>
                  </el-tooltip>

                  <!-- 详情按钮 -->
                  <el-tooltip :content="$t('message.random.details')" placement="top">
                    <el-button :type="state.activeTabs[image.id] === 'detail' ? 'primary' : 'text'"
                      @click.stop="changeTab(image.id, 'detail')">
                      <el-icon>
                        <Document />
                      </el-icon>
                    </el-button>
                  </el-tooltip>

                  <!-- 标签按钮 -->
                  <el-tooltip :content="$t('message.random.tags')" placement="top">
                    <el-button :type="state.activeTabs[image.id] === 'tags' ? 'primary' : 'text'"
                      @click.stop="changeTab(image.id, 'tags')">
                      <el-icon>
                        <PriceTag />
                      </el-icon>
                    </el-button>
                  </el-tooltip>

                  <!-- 元数据按钮 -->
                  <el-tooltip :content="$t('message.random.metadata')" placement="top">
                    <el-button :type="state.activeTabs[image.id] === 'metadata' ? 'primary' : 'text'"
                      @click.stop="changeTab(image.id, 'metadata')">
                      <el-icon>
                        <DataAnalysis />
                      </el-icon>
                    </el-button>
                  </el-tooltip>
                  <el-tooltip :content="`${image.disliked}`" placement="top">
                    <el-button @click.stop="switchDisliked(image)" :type="image.disliked == 1? 'danger':'primary'" icon="ele-Delete">
                    </el-button>
                  </el-tooltip>
                </div>
              </div>
            </template>

            <!-- 内容区域 - 根据当前选项卡显示不同内容 -->
            <div class="content-wrapper">
              <!-- 图片内容 -->
              <div v-if="state.activeTabs[image.id] === 'image'" class="image-wrapper">
                <el-image :src="getProcessedImageUrl(image.id)" :preview-src-list="[getProcessedImageUrl(image.id)]"
                 preview-teleported hide-on-click-modal fit="contain" class="preview-image" />
              </div>

              <!-- 详情内容 -->
              <div v-if="state.activeTabs[image.id] === 'detail'" class="detail-content">
                <el-scrollbar class="detail-inner" >
                  <el-row class="mb5">
                    <el-text size="default" class="mb5">{{ image.id }}</el-text>
                  </el-row>
                  <el-row class="mb5">
                    <el-col class="mb5" :span="24">
                      <el-select v-model="image.class_type" :placeholder="$t('message.random.selectClassType')">
                        <el-option v-for="item in state.classType" :key="item.value" :label="item.label" :value="item.value" />
                      </el-select>
                    </el-col>
                    <el-col class="mb5" :span="24">
                      <el-input v-stop-comfy-events v-model="image.customize_name" :placeholder="$t('message.random.customizeName')" />
                    </el-col>
                    <el-col class="mb5" :span="24">
                      <el-input v-stop-comfy-events v-model="image.name" :placeholder="$t('message.random.keyName')" />
                    </el-col>
                    <el-col class="mb5" :span="24">
                      <div class="rate-container">
                        <el-rate size="default" v-model="image.rating" :max="10" allow-half clearable
                          score-template="{value} points" />
                      </div>
                    </el-col>
                    <el-col class="mb5" :span="24">
                      <div class="switch-container">
                        <el-text>{{ $t('message.random.favorite') }}:</el-text>
                        <el-switch v-model="image.favorite" inline-prompt :active-text="$t('message.common.yes')"
                          :active-value="1" :inactive-value="0" :inactive-text="$t('message.common.no')" />
                      </div>
                      <div class="switch-container">
                        <el-text>{{ $t('message.random.disliked') }}:</el-text>
                        <el-switch v-model="image.disliked" inline-prompt :active-value="1" :inactive-value="0"
                          :active-text="$t('message.common.yes')" :inactive-text="$t('message.common.no')" />
                      </div>
                    </el-col>
                    <el-col class="mb5" :span="24">
                      <div class="created-at-container">
                        <el-text size="default">{{ $t('message.random.createdAt') }}:</el-text>
                        <el-text size="default" class="text-truncate">{{ image.created_at }}</el-text>
                      </div>
                    </el-col>
                    <el-col class="mb5" :span="24">
                      <el-button size="default" type="primary" @click="handleFormSubmit(image)" class="submit-btn">
                          {{ $t('message.common.submit') }}
                        </el-button>
                    </el-col>
                  </el-row>
                </el-scrollbar>
              </div>

              <!-- 标签内容 -->
              <div v-if="state.activeTabs[image.id] === 'tags'" class="tags-content">
                <el-row>
                  <el-col :span="24">
                    <el-form-item>
                      <el-input v-stop-comfy-events v-model="image.tags" type="textarea" :autosize="{ minRows: 10, maxRows: 15 }"
                        :placeholder="$t('message.random.noTags')" />
                    </el-form-item>
                  </el-col>
                </el-row>
              </div>

              <div v-if="state.activeTabs[image.id] === 'metadata'" class="metadata-content">
              </div>
            </div>
          </el-card>
        </div>
      </div>
    </div>
    <EditForm ref="editForm" @submit="handleFormSubmit" />
    <Contextmenu ref="contextmenuRef" :menu-items="state.contextMenuItems" :dropdown="state.dropdown"
      @current-contextmenu-click="handleContextMenuClick" />

    <!-- 全局上传组件 -->
    <el-upload
      v-show="false"
      ref="imageUploader"
      action=""
      :show-file-list="false"
      :before-upload="beforeImageUpload"
      accept="image/*"
    >
    </el-upload>
  </div>
</template>

<script setup lang="ts">
import { reactive, defineAsyncComponent, ref, watch, nextTick, onMounted, onUnmounted, computed, getCurrentInstance } from 'vue'
import { ElMessage } from 'element-plus'
import { useConfigStore } from '@renderer/stores/configStore'
import { throttle } from 'lodash-es'
import { useExPrompt } from '@renderer/stores/useExPrompt'

const instance = getCurrentInstance();
const cssVar = instance?.appContext.config.globalProperties.$cssVarName;
const configStore = useConfigStore()
const exPromptStore = useExPrompt()

const Contextmenu = defineAsyncComponent(
  () => import('@renderer/views/common/component/contextmenu.vue')
)
const EditForm = defineAsyncComponent(
  () => import('@renderer/views/common/component/EditFrom.vue')
)

// 定义父组件传过来的值
const props = defineProps({
  data: {
    type: Array,
    default: () => []
  },
  config: {
    type: Object,
    default: () => { }
  },
  param: {
    type: Object,
    default: () => { }
  }
})

// 定义子组件向父组件传值/事件
const emit = defineEmits(['delRow', 'edit', 'replaceImage'])

// 上传相关
const imageUploader = ref();
const currentReplaceImage = ref("");

// 虚拟滚动相关
const gridContainer = ref<HTMLElement | null>(null);
const cardHeight = ref(360); // 卡片实际高度（响应式）
const gapHeight = 20; // 卡片之间的间隙
const rowHeight = computed(() => cardHeight.value + gapHeight); // 计算行高 = 卡片高度 + 间隙
const columnCount = ref(4); // 初始列数
const scrollTop = ref(0);
const containerHeight = ref(500); // 默认设置一个合理的初始高度
let resizeObserver: ResizeObserver | null = null;
const visibleImagesCache = ref<any[]>([]);

// 图片处理
const getProcessedImageUrl = (id: string) => {
  if (!id) return ''
  return configStore.comfyProxyImage(`file://${configStore.config.imagesPath}\\collections\\${id}.webp`)
}

// 组件引用
const editForm = ref()
const contextmenuRef = ref()

// 组件状态
const state = reactive({
  activeTabs: {} as Record<string, 'image' | 'detail' | 'tags' | 'metadata'>,
  loading: false,
  selectlist: [],
  checkListAll: true,
  checkListIndeterminate: false,
  dropdown: { x: 0, y: 0 },
  contextMenuItems: [
    { id: 'edit', txt: '修改', icon: 'ele-Edit', action: 'edit' },
    { id: 'delete', txt: '删除', icon: 'ele-Delete', action: 'delete' },
    { id: 'replace', txt: '更换封面', icon: 'ele-Picture', action: 'replace' },
    { id: 'copy', txt: '复制内容', icon: 'ele-DocumentCopy', action: 'copy' },
    { id: 'send', txt: '发送到随机面板', icon: 'ele-DocumentCopy', action: 'send' }
  ],
  classType:[
    {label:'collect',value:'collect'},
    {label:'style',value:'style'},
    {label:'action',value:'action'},
    {label:'cloth',value:'cloth'},
    {label:'negative',value:'negative'}
  ]
})

// 重置滚动位置
const resetScrollPosition = () => {
  if (gridContainer.value) {
    gridContainer.value.scrollTop = 0;
    scrollTop.value = 0;
  }
}

// 虚拟滚动计算属性
const totalRows = computed(() => {
  return Math.ceil(props.data.length / columnCount.value);
});

const totalHeight = computed(() => {
  return totalRows.value * rowHeight.value;
});

const startRow = computed(() => {
  return Math.max(0, Math.floor(scrollTop.value / rowHeight.value) - 1);
});

const endRow = computed(() => {
  return Math.min(totalRows.value, Math.ceil((scrollTop.value + containerHeight.value) / rowHeight.value) + 1);
});

/*
const visibleImages = computed(() => {
  const startIndex = Math.max(0, startRow.value * columnCount.value);
  const endIndex = Math.min(props.data.length, (endRow.value + 1) * columnCount.value);

  // 缓存可见项以减少重新渲染
  const newVisibleImages = props.data.slice(startIndex, endIndex);

  // 只有当可见项确实改变时才更新缓存
  const isSame = newVisibleImages.length === visibleImagesCache.value.length &&
                 newVisibleImages.every((item, index) =>
                   item.id === visibleImagesCache.value[index]?.id);

  if (!isSame) {
    visibleImagesCache.value = newVisibleImages;
  }

  return visibleImagesCache.value;
});
*/
const visibleImages = computed(() => {
  const startIndex = Math.max(0, startRow.value * columnCount.value);
  const endIndex = Math.min(props.data.length, (endRow.value + 1) * columnCount.value);
  return props.data.slice(startIndex, endIndex);
});

// 处理滚动事件
const handleScroll = throttle(() => {
  if (gridContainer.value) {
    scrollTop.value = gridContainer.value.scrollTop;
  }
}, 16);

// 更新列数响应式
const updateColumnCount = () => {
  if (!gridContainer.value) return;

  const containerWidth = gridContainer.value.clientWidth;
  columnCount.value = Math.max(1, Math.floor(containerWidth / 280));
};

// 响应容器大小变化
const setupResizeObserver = () => {
  if (!gridContainer.value) return;

  resizeObserver = new ResizeObserver(entries => {
    for (const entry of entries) {
      if (entry.target === gridContainer.value) {
        containerHeight.value = entry.contentRect.height;
        updateColumnCount();
      }
    }
  });

  resizeObserver.observe(gridContainer.value);
};

// 右键菜单处理
const onContextmenu = (image: any, e: MouseEvent) => {
  const { clientX, clientY } = e
  state.dropdown.x = clientX
  state.dropdown.y = clientY
  contextmenuRef.value.openContextmenu(image)
}

// 处理右键菜单点击
const handleContextMenuClick = async ({ menuItem, contextItem }) => {
  switch (menuItem.action) {
    case 'edit':
      handleFormSubmit(contextItem)
      break
    case 'delete':
      emit('delRow', contextItem.id)
      break
    case 'replace':
      handleReplace(contextItem.id)
      break
    case 'copy':
      navigator.clipboard
        .writeText(contextItem.tags)
        .then(() => ElMessage.success('内容已复制'))
        .catch(() => ElMessage.error('复制失败'))
      break
    case 'send':
      const state = {
          id: contextItem.id,
          name: contextItem.name,
          type: contextItem.class_type,
          customize_name: contextItem.customize_name,
          tags: contextItem.tags,
          rating: contextItem.rating,
          favorite: contextItem.favorite,
          disliked: contextItem.disliked,
      }
      exPromptStore.updateStateByType(state);
      ElMessage.success(`send ${state.type} to random`)
      break;
  }
}

// 处理替换图片
const handleReplace = (id) => {
  currentReplaceImage.value = id;
  nextTick(() => {
    imageUploader.value?.$el.querySelector('input[type="file"]')?.click();
  });
}

// 图片上传前的处理
const beforeImageUpload = async (file: File) => {
  try {
    if (!['image/jpeg', 'image/png', 'image/jpg'].includes(file.type)) {
      ElMessage.error('仅支持 JPG/JPEG/PNG 格式')
      return false
    }

    if (file.size > 5 * 1024 * 1024) {
      ElMessage.error('文件大小不能超过5MB')
      return false
    }
    const id =  currentReplaceImage.value
    emit('replaceImage', id,file)
    currentReplaceImage.value = "";

    return false;
  } catch (error) {
    ElMessage.error(`转换失败: ${error.message}`)
    return false
  }
}

const switchDisliked = (image:any)=>{
  const data = {
    disliked: !image.disliked,
    id: image.id
  }
  emit('edit',data)
}

// 处理表单提交
const handleFormSubmit = (formData: any) => {
  emit('edit', formData)
}

const handleClickEvent = () => {
  contextmenuRef.value.closeContextmenu()
}

// 切换选项卡
const changeTab = (id: string, tab: 'image' | 'detail' | 'tags' | 'metadata') => {
  state.activeTabs[id] = tab
  // 确保切换标签时不影响卡片尺寸
  nextTick(() => {
    if (gridContainer.value) {
      gridContainer.value.style.display = 'none';
      gridContainer.value.offsetHeight; // 触发重绘
      gridContainer.value.style.display = '';
    }
  });
}

// 响应式调整卡片高度
const updateCardHeight = () => {
  if (window.innerWidth < 768) {
    return 320;
  } else if (window.innerWidth < 992) {
    return 340;
  } else if (window.innerWidth < 1200) {
    return 360;
  } else if (window.innerWidth < 1400) {
    return 380;
  }
  return 400;
};

// 监听数据变化
watch(() => props.data, (newData) => {
  newData.forEach(item => {
    if (!state.activeTabs[item.id]) {
      state.activeTabs[item.id] = 'image'
    }
  })
}, { immediate: true })

// 监听cardHeight变化
watch(cardHeight, () => {
  nextTick(() => {
    updateColumnCount();
    if (gridContainer.value) {
      const currentScroll = gridContainer.value.scrollTop;
      gridContainer.value.scrollTop = 0;
      gridContainer.value.scrollTop = currentScroll;
    }
  });
});

// 生命周期钩子
onMounted(() => {
  cardHeight.value = updateCardHeight();

  if (gridContainer.value) {
    containerHeight.value = gridContainer.value.clientHeight || 500;
    updateColumnCount();
    setupResizeObserver();
  }

  const handleResize = () => {
    cardHeight.value = updateCardHeight();
    updateColumnCount();
  };

  window.addEventListener('resize', handleResize);

  onUnmounted(() => {
    window.removeEventListener('resize', handleResize);
  });
});

onUnmounted(() => {
  if (resizeObserver) {
    resizeObserver.disconnect();
  }
});

defineExpose({
  resetScrollPosition
})
</script>

<style scoped lang="scss">
.table-container {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: calc(var(--local-mount-height) - 180px);
}

.image-grid-container {
  flex: 1;
  position: relative;
  overflow-y: auto;
  background: var(--el-bg-color-page);
  border-radius: 8px;
  padding: 16px;
  will-change: transform;
  contain: strict;
  min-height: 300px;
}

.image-grid-phantom {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: -1;
}

.image-grid-content {
  position: absolute;
  top: 16px;
  left: 16px;
  right: 16px;
  display: grid;
  gap: 16px;
  will-change: transform;
  backface-visibility: hidden;
  perspective: 1000;
  transform: translateZ(0);
}

.grid-item {
  width: 100%;
  box-sizing: border-box;
}

// 调整卡片头部内边距
:deep(.el-card__header) {
  padding: 6px 10px; // 减小头部内边距
  background: var(--el-bg-color-overlay);
  border-bottom: 1px solid var(--el-border-color);
  box-sizing: border-box;
}

// 调整卡片内容区域内边距
:deep(.el-card__body) {
  padding: 8px; // 减小内容区域内边距，这是减少整体大小的关键
}

.image-card {
  border-radius: 12px;
  overflow: hidden;
  transition: all 0.3s ease;
  border: none;
  background: var(--el-bg-color);
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
  box-sizing: border-box;

  &:hover {
    transform: translateY(-5px);
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.12);
  }

  :deep(.el-card__header) {
    padding: 10px 15px;
    background: var(--el-bg-color-overlay);
    border-bottom: 1px solid var(--el-border-color);
    box-sizing: border-box;
  }

  .card-header {
    display: flex;
    justify-content: center;
    align-items: center;
  }

  .icon-buttons {
    display: flex;
    gap: 4px;

    .el-button {
      padding: 6px 8px;
      border-radius: 6px;
      transition: all 0.2s;

      &:hover {
        background: var(--next-color-hover-rgba);
        transform: scale(1.05);
      }

      i {
        font-size: 16px;
      }
    }
  }
}

.content-wrapper {
  height: calc(100% - 56px);
  display: flex;
  flex-direction: column;
  padding: 8px;
  box-sizing: border-box;
  overflow: hidden;
}

.image-wrapper {
  position: relative;
  height: 100%;
  border-radius: 8px;
  overflow: hidden;
  background: var(--el-bg-color);
  display: flex;
  align-items: center;
  justify-content: center;

  .preview-image {
    width: 100%;
    height: 100%;
    border-radius: 6px;
    transition: transform 0.3s ease;
    object-fit: contain;
    &:hover {
      transform: scale(1.02);
    }
  }
}

// 详情内容样式
.detail-content {
  height: 100%;
  overflow-y: auto;
  box-sizing: border-box;

  .detail-inner {
    width: 100%;
    height: 250px;
    box-sizing: border-box;
  }

  .el-row {
    margin-bottom: 8px;
    width: 100%;
    box-sizing: border-box;
  }

  .el-col {
    width: 100% !important;
    box-sizing: border-box !important;
    padding: 0 !important;
  }

  .el-text {
    display: block;
    margin-bottom: 5px;
    color: var(--el-text-color-regular);
    font-weight: 500;
    box-sizing: border-box;
  }

  .el-select, .el-input {
    width: 100% !important;
    box-sizing: border-box !important;
  }

  .text-truncate {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .switch-container {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
    flex-wrap: nowrap;
  }

  .created-at-container {
    display: flex;
    align-items: center;
    gap: 5px;
    flex-wrap: wrap;
  }

  .rate-container {
    display: flex;
    align-items: center;
  }

  .submit-btn {
    margin-left: auto;
  }
}

.tags-content {
  height: 100%;
  padding: 5px;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;

  .el-textarea {
    flex: 1;

    :deep(.el-textarea__inner) {
      height: 100% !important;
      padding: 10px;
      border-radius: 8px;
      background: var(--el-bg-color);
      border: 1px solid var(--el-border-color);
      transition: border-color 0.3s;
      box-sizing: border-box;

      &:focus {
        border-color: var(--el-color-primary);
        box-shadow: 0 0 0 2px rgba(187, 134, 252, 0.2);
      }
    }
  }
}

.metadata-content {
  height: 100%;
  padding: 10px;
  background: var(--el-bg-color);
  border-radius: 8px;
  color: var(--el-text-color-regular);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  box-sizing: border-box;
}

.table-footer {
  display: flex;
  justify-content: center;
  margin-top: 20px;
  padding: 15px 0;
  background: var(--el-color-white);
  border-radius: 8px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
}

.mt15 {
  margin-top: 15px;
}

.mb5 {
  margin-bottom: 5px !important;
}


@media (max-width: 768px) {
  .image-card {
    margin-bottom: 15px;
  }

  .image-wrapper {
    height: 220px;
  }

  .detail-content {
    padding: 5px;
  }
}
</style>
